import SocketProtocol from "../scripts/SocketProtocol";
import SocketManager from "../scripts/SocketManager";
import { SocketState } from "../scripts/State/SocketState";
import demoPlayer from "./demoPlayer";
import SocketConfig from "../scripts/SocketConfig";

const { ccclass, property } = cc._decorator;

@ccclass
export default class demoTS extends cc.Component {

    @property({ type: cc.Label, displayName: "打印" })
    dialog: cc.Label = null;

    @property({ type: cc.Asset, displayName: "证书" })
    ssl: cc.Asset = null;

    private join_room_panel: cc.Node;

    start() {
        SocketConfig.cert = this.ssl;
        //初始化全局唯一的服务器管理器并连接服务器
        SocketManager.init(this.connectSuccessed.bind(this), this.connectFailed.bind(this), this.connectClosed.bind(this), this.messageManager.bind(this));

        //发送心跳
        this.schedule(this.sendHeart.bind(this), 20);
        //初始化连接界面
        this.initConnectPanel();
        //初始化登录界面
        this.initLogin();
        //初始化加入/匹配房间界面
        this.initMatchPanel();
        //初始化房间界面
        this.initRoomPanel();

        console.log(this.node.getComponent(cc.PolygonCollider));
    }

    /**
     * 连接成功回调
     */
    private connectSuccessed() {
        this.showLog(">>>>>服务器连接成功");
        this.login_panel.active = true;
        this.connect_panel.active = false;

    }

    /**
     * 连接失败回调
     * @param err 错误信息
     */
    private connectFailed(err: object) {
        this.showLog(">>>>>服务器连接失败");
        this.connect_panel.active = true;

        this.loaing_lable.active = false;
        this.btn_reconnect.active = true;

        this.login_panel.active = false;
        this.match_panel.active = false;
        this.room_panel.active = false;
    }

    /**
     * 关闭连接回调
     * @param data 关闭参数
     */
    private connectClosed(data: object) {
        this.showLog(">>>>>与服务器断开连接");
        this.connect_panel.active = true;

        this.loaing_lable.active = false;
        this.btn_reconnect.active = true;

        this.login_panel.active = false;
        this.match_panel.active = false;
        this.room_panel.active = false;
    }

    /**
     * 统一的消息管理器 如果返回的服务id没有被注册，则统一将消息发布到这个方法中
     * @param data 接收到的数据
     */
    private messageManager(data: object) {
        console.log("通用回调函数:", data);
    }

    /**
     * 发送心跳
     */
    private sendHeart() {
        if (SocketManager.isConnect()) SocketManager.heartBeat();
    }
    /**
     * 输出到屏幕上
     * @param content 输出内容 
     */
    private showLog(content: string) {
        this.dialog.unscheduleAllCallbacks();
        this.dialog.string = content;
        this.dialog.scheduleOnce(function () {
            this.dialog.string = "";
        }.bind(this), 3);
    }

    //#region 0.连接服务器

    //连接界面
    private connect_panel: cc.Node;
    //加载文字
    private loaing_lable: cc.Node;
    //重接按钮
    private btn_reconnect: cc.Node;

    /**
     * 初始化连接界面
     */
    private initConnectPanel() {
        this.connect_panel = this.node.getChildByName("connecting");
        this.connect_panel.on(cc.Node.EventType.TOUCH_END, function () { });
        this.loaing_lable = this.connect_panel.getChildByName('loading_text');
        this.btn_reconnect = this.connect_panel.getChildByName('btn_reconncet');
        this.btn_reconnect.on(cc.Node.EventType.TOUCH_END, this.reconnect.bind(this));
    }

    /**
     * 重新连接服务器
     */
    private reconnect() {
        this.loaing_lable.active = true;
        this.btn_reconnect.active = false;
        //初始化全局唯一的服务器管理器并连接服务器
        SocketManager.init(this.connectSuccessed.bind(this), this.connectFailed.bind(this), this.connectClosed.bind(this), this.messageManager.bind(this));
    }
    //#endregion

    //#region 1.登录服务器
    //登录界面
    private login_panel: cc.Node;
    //uid输入框
    private uid_input: cc.EditBox;
    //玩家uid
    private uid: number;

    /**
     * 初始化登录界面
     */
    private initLogin() {
        this.login_panel = this.node.getChildByName("login");
        this.login_panel.getChildByName("btn_login").on(cc.Node.EventType.TOUCH_END, this.Login.bind(this));
        this.uid_input = this.login_panel.getChildByName("uid").getComponent(cc.EditBox);

        SocketManager.register(SocketProtocol.LOGINGAME, this.loginResp.bind(this))
    }

    /**
     * 登录服务器
     */
    private Login() {
        if (this.uid_input.textLabel.string != null && this.uid_input.textLabel.string != '') {
            this.uid = parseInt(this.uid_input.textLabel.string);
            let data = {
                name: "test",
                image: "https://cdn.lewhy.xyz"
            }
            SocketManager.login(this.uid, JSON.stringify(data));
        } else {
            this.showLog("uid不能为空");
        }
    }

    /**
     * 登录成功的回调
     * @param data 服务器返回数据
     */
    private loginResp(data: object) {
        console.log("登录返回数据:", data);
        this.match_panel.active = true;
        this.login_panel.active = false;
    }
    //#endregion 1.连接服务器

    //#region 2.匹配房间
    private match_panel: cc.Node;//匹配/加入指定房间界面
    private room_tag_input: cc.EditBox;//房间标签输入框
    private room_id_input: cc.EditBox;//房间号码输入框
    private btn_join_room: cc.Node;//加入指定房间
    private btn_match_room: cc.Node;//匹配房间

    /**
     * 初始化匹配/加入指定房间界面
     */
    private initMatchPanel() {
        this.match_panel = this.node.getChildByName('match_room');
        this.room_tag_input = this.match_panel.getChildByName('room_tag').getComponent(cc.EditBox);
        this.room_id_input = this.match_panel.getChildByName('room_id').getComponent(cc.EditBox);
        this.btn_join_room = this.match_panel.getChildByName('btn_join_room');
        this.btn_match_room = this.match_panel.getChildByName('btn_match_room');

        this.btn_join_room.on(cc.Node.EventType.TOUCH_END, this.joinRoom.bind(this));
        this.btn_match_room.on(cc.Node.EventType.TOUCH_END, this.matchRoom.bind(this));

        SocketManager.register(SocketProtocol.MATCHROOM, this.matchResp.bind(this));
        SocketManager.register(SocketProtocol.JOINROOM, this.joinResp.bind(this));
    }

    //加入指定房间
    private joinRoom() {
        if (this.room_tag_input.textLabel.string != null && this.room_tag_input.textLabel.string != '') {
            if (this.room_id_input.textLabel.string != null && this.room_id_input.textLabel.string != '') {
                SocketManager.joinRoom(this.room_tag_input.textLabel.string, this.room_id_input.textLabel.string);
            } else {
                this.showLog("房间id不能为空");
            }
        } else {
            this.showLog("房间标签不能为空");
        }
    }

    //匹配房间
    private matchRoom() {
        if (this.room_tag_input.textLabel.string != null && this.room_tag_input.textLabel.string != '') {
            //向服务器发送匹配请求，demo中player_count发送，表示房间最大容纳玩家数为2
            SocketManager.matchRoom(this.room_tag_input.textLabel.string, 2);
        } else {
            this.showLog("房间标签不能为空");
        }
    }

    /**
     * 匹配房间回调
     * @param data 服务器返回数据
     */
    private matchResp(data: any) {
        console.log("匹配房间回调", data);
        if (data.state && data.state == SocketState.SUCCESSED) {
            this.enterRoom(data);
        }
    }

    /**
     * 加入房间回调
     * @param data 服务器返回数据
     */
    private joinResp(data: any) {
        console.log("加入房间回调", data);
        if (data.state && data.state == SocketState.SUCCESSED) {
            this.enterRoom(data);
        }
    }

    //#endregion 2.匹配房间

    //#region 3.房间界面
    private room_panel: cc.Node;
    //房间id
    private room_id: cc.Label;

    /**
     * 测试数据输入框
     */
    private data_input: cc.EditBox;
    /**
     * 准备按钮
     */
    private btn_ready: cc.Node;
    /**
     * 加载完成
     */
    private btn_loaded: cc.Node;
    /**
     * 广播测试按钮
     */
    private btn_send_data: cc.Node;

    /**
     * 获取房间玩家列表
     */
    private btn_get: cc.Node;

    /**
     * 退出房间按钮
     */
    private btn_leave: cc.Node;

    /**
     * 自己的信息
     */
    private self: demoPlayer;

    /**
     * 对手的信息
     */
    private other: demoPlayer;

    /**
     * 初始化房间界面
     */
    private initRoomPanel() {
        this.room_panel = this.node.getChildByName('room_panel')
        this.room_id = this.room_panel.getChildByName("room_id").getComponent(cc.Label);
        this.btn_ready = this.room_panel.getChildByName('btn_ready');
        this.btn_loaded = this.room_panel.getChildByName('btn_loaded');
        this.btn_leave = this.room_panel.getChildByName('btn_leave');
        this.btn_send_data = this.room_panel.getChildByName('btn_send_data');
        this.btn_get = this.room_panel.getChildByName('btn_get');

        this.data_input = this.room_panel.getChildByName('send_data').getComponent(cc.EditBox);

        this.btn_ready.on(cc.Node.EventType.TOUCH_END, this.readyGame.bind(this));
        this.btn_loaded.on(cc.Node.EventType.TOUCH_END, this.loadedGame.bind(this));
        this.btn_leave.on(cc.Node.EventType.TOUCH_END, this.leaveRoom.bind(this));
        this.btn_send_data.on(cc.Node.EventType.TOUCH_END, this.sendData.bind(this));
        this.btn_get.on(cc.Node.EventType.TOUCH_END, this.getPlayers.bind(this));

        SocketManager.register(SocketProtocol.READYGAME, this.onReadyGame.bind(this));
        SocketManager.register(SocketProtocol.LOADEDGAME, this.onLoadedGame.bind(this));
        SocketManager.register(SocketProtocol.LEAVEROOM, this.onLeaveRoom.bind(this));
        SocketManager.register(SocketProtocol.SEBROADCAST, this.onSendData.bind(this));

        SocketManager.register(SocketProtocol.REBROADCAST, this.onReceiveData.bind(this));
        SocketManager.register(SocketProtocol.OTHERJOIN, this.onOtherJoin.bind(this));
        SocketManager.register(SocketProtocol.OTHERLEAVE, this.onOtherLeave.bind(this));
        SocketManager.register(SocketProtocol.GETPLAYERS, this.onGetPlayers.bind(this));

        this.self = this.room_panel.getChildByName("self").getComponent(demoPlayer).Init();
        this.other = this.room_panel.getChildByName("other").getComponent(demoPlayer).Init();
    }

    /**
     * 进入房间
     */
    private enterRoom(data) {
        this.room_panel.active = true;
        this.match_panel.active = false;
        this.btn_ready.active = true;
        this.btn_loaded.active = false;
        this.data_input.textLabel.string = "";
        this.other.node.active = false;
        this.self.ready.active = false;
        this.other.ready.active = false;
        this.self.uid.string = "uid:" + this.uid;
        this.room_id.string = data.room_id;

        if (data.player_list && data.player_list.length > 0) {
            this.other.uid.string = "uid:" + data.player_list[0].uid;
            this.other.node.active = true;
            if (data.player_list[0].isReady == 1) {
                this.other.ready.active = true;
            }
        }
    }

    /**
     * 离开房间
     */
    private leaveRoom() {
        SocketManager.leaveRoom();
    }

    /**
     * 准备游戏
     */
    private readyGame() {
        SocketManager.readyGame();
    }

    /**
     * 加载完毕
     */
    private loadedGame() {
        SocketManager.loadedGame();
    }

    /**
     * 发送广播
     */
    private sendData() {
        if (this.data_input.textLabel.string != null && this.data_input.textLabel.string != "") {
            SocketManager.broadcast(this.data_input.textLabel.string, "test", false);
        }
    }

    private getPlayers() {
        SocketManager.getRoomPlayers();
    }

    /**
     * 准备游戏回调
     * @param data 
     */
    private onReadyGame(data) {
        console.log("准备游戏回调", data);
        console.log(this.uid);
        for (let i = 0; i < data.ready_state.length; i++) {
            if (this.uid == data.ready_state[i]) {
                this.self.ready.active = true;
            } else {
                this.other.ready.active = true;
            }
        }
    }

    /**
     * 加载完成回调
     * @param data 
     */
    private onLoadedGame(data) {
        console.log("加载完成回调", data);
    }

    /**
     * 离开房间回调
     * @param data 
     */
    private onLeaveRoom(data) {
        console.log("离开房间回调", data);
        this.room_panel.active = false;
        this.match_panel.active = true;
    }

    /**
     * 发送广播回调
     * @param data 
     */
    private onSendData(data) {
        console.log("发送广播回调", data);
    }

    /**
     * 当其他玩家加入
     */
    private onOtherJoin(data) {
        console.log("当其他玩家加入", data);
        let player_data = JSON.parse(data.player_data);
        this.other.node.active = true;
        this.other.uid.string = "uid:" + player_data.uid
    }

    /**
     * 当其他玩家离开
     */
    private onOtherLeave(data) {
        console.log("当其他玩家离开", data);
        this.other.node.active = false;
        this.other.ready.active = false;
    }

    /**
     * 接收到广播
     */
    private onReceiveData(data) {
        console.log("接收到广播", data);
        this.showLog(data.data);
    }

    /**
     * 获取房间内其他玩家数据
     */
    private onGetPlayers(data) {
        console.log("获取房间内其他玩家数据", data);
    }
    //#endregion
}
